<?php
class fwModelRecord {
    /*
     * Класс служит для более удобной работы с базой данных.
     * При обращении к классу, создается объект, содержащий строку из таблицы.
     * Используемые методы:
     * find() - используется для поиска строки, все данные считываются в созданный объект
     * setCollname($value) - устанавливает значение $value в созданном объекте.
     * Служит при создании новой записи или замены записи в базе данных.
     * getCollname() - получить значение для ячейки.
     */
    protected $table = null;
    protected $data = array();
    protected $fields = array();

    /*
     * Contains an array of fields that are required to create a new record.
     */
    protected $require_fields = array();

    /*
     * Trigger. If model get by find() method, is not new record.
     * And must be UPDATE on save method, else INSERT new record.
     */
    protected $isnew = true;

    /*
     * Trigger. If model use set() method, than model must be saved in database.
     */
    protected $save = false;

    /*
     * Trigger. Must be defined in children class. Do not change it here!
     * If trigger is set true, than try to set time() in `created` field on new record.
     */
    protected $created = false;

    /*
     * Trigger like created. But set time() to `updated` field on record update
     */
    protected $updated = false;

    /*
     * Trigger. Must be defined in children class. Do not change it here!
     * If trigger is set true, than try to set "user id" in `author` field on new record.
     */
    protected $author = false;

    public function __construct($table=null,$require_fields=array()) {
        
        if($table) $this->table = $table;
        else return;
        if(count($require_fields)) $this->require_fields = $require_fields;
        register_shutdown_function(array($this,"save"));
        $this->listFields();
    }
    public function __call($method, $args = array()) {
        $m = U::explodeCase($method);
        if($m[0] == "set" && count($args) == 1) {
            return $this->set(implode("_", array_slice($m, 1)), $args[0]);
        } elseif($m[0] == "get" && count($args) == 0) {
            return $this->get(implode("_", array_slice($m, 1)));
        } else {
            return null;
        }
    }
    public function get($field) {
        if(is_array($field)) { $field = array_shift($field); }
        S::settings()->set("db.language.fields",array());
        if(in_array($field,array_keys($this->data))) {
            return $this->data[$field];
        } elseif(count(S::settings()->get("language")) && in_array($field, S::settings()->get("db.language.fields"))) {
            if(S::route()->getLanguage() == S::settings()->getDefault("language")) {
                return $this->data[$field];
            } else {
                return $this->data[$field.'_'.S::route()->getLanguage()];
            }
        } else {
            return null;
        }
    }
    public function set($field, $value) {
        $this->save = true;
        $this->data[$field] = $value;
    }
    public function doClone() {
        $this->isnew = true;
        unset($this->data["id"]);
    }
    public function expand() {
        return $this->data;
    }
    public function counter() {
        if(isset($this->data["id"]) && is_numeric($this->data["id"])) {
            S::db()->query("UPDATE `".$this->table."` SET `counter` = `counter` + 1 WHERE `id` = ?d",$this->data["id"]);
        }
    }
    public function find() {
        $args = func_get_args();
        $query = array_shift($args);
        if(is_integer($query)) {
            $result = S::db()->selectRow("SELECT * FROM ?_".$this->table." WHERE `id` = ?",intval($query));
            if(count($result)) {
                $this->data=$result;
                $this->isnew = false;
            }
        } else {
            $result = S::db()->selectRow("SELECT * FROM ?_".$this->table." WHERE ".$query,$args);
            if(count($result)) {
                $this->data=$result;
                $this->isnew = false;
            }
        }
        if(count($this->data) > 0) {
            return true;
        }
        return false;
    }

    public function save($getId=false) {
        if(!$this->save) return;
        $this->save = false; // Do not double save
        if(count($this->require_fields) > 0) {
            foreach($this->require_fields as $rf) {
                if(!isset($this->data[$rf])) return;
            }
        }

        if($this->isnew && count($this->data) > 0) {
            if($this->created) { $this->data["created"] = time(); }
            if($this->author && S::model("groups")->checkRole("user")) { $this->data["author"] = S::model("account")->getId(); }
            $q = "INSERT INTO `".$this->table."` (`".implode("`,`", array_keys($this->data))."`) VALUES ('".implode("','",array_values($this->data))."')";
            $result = S::db()->query($q);
            if($getId) return $result;
        } elseif(!$this->isnew && count($this->data) > 1 && isset($this->data["id"]) && $this->data["id"] > 0){
            if($this->updated) $this->data["updated"] = time();
            $fv=array();
            foreach($this->fields as $k=>$v) {
                if($k == "id") continue;
                $fv[] = "`".$k."`='".$this->data[$k]."'";
            }
            $q = "UPDATE ".$this->table." SET ".implode(",",$fv)." WHERE `id` = ?d";
            S::db()->query($q,$this->data["id"]);
            if($getId) return $this->data["id"];
        }
    }
    public function listFields() {

        if(count($this->fields) == 0 && $this->table) {

            $q = S::db()->select("desc ".$this->table);
            if(is_array($q) && count($q) > 0) {
                foreach($q as $v) {
                    $this->fields[$v["Field"]] = $v;
                }
            }
        }
        return $this->fields;
    }

    public function request() {
        foreach($_POST as $k=>$v) {
            if(in_array($k,array_keys($this->listFields()))) {
                $this->set($k,$v);
            }
        }
    }
    public function load() {
        foreach($this->fields as $field) {
            if(isset($_POST[$field["Field"]])) {
                $this->set($field["Field"],htmlspecialchars($_POST[$field["Field"]]));
            }
        }
    }
}
?>